package main

import (
	"context"
	"fmt"
	consulapi "github.com/hashicorp/consul/api"
	_ "github.com/mbobakov/grpc-consul-resolver" // It's important
	"github.com/opentracing/opentracing-go"
	"google.golang.org/grpc"
	"google.golang.org/grpc/health"
	"google.golang.org/grpc/health/grpc_health_v1"
	"jaeger-demo/common"
	"jaeger-demo/otgrpc"
	"jaeger-demo/proto"
	"jaeger-demo/utils"
	"net"
	"time"
)

// https://www.cnblogs.com/liuqingzheng/p/16322702.html
func main() {
	port, _ := utils.GetCanUsePort()

	// 启动服务时使用拦截器
	// 第一步：new一个server，增加jeager的服务端拦截器
	// 定义一个新的trace，以后从service中就可以取出父的span
	tracer, closer := utils.GetTracer()
	defer closer.Close()
	// 设置成全局tracer
	opentracing.SetGlobalTracer(tracer)
	g := grpc.NewServer(grpc.UnaryInterceptor(otgrpc.OpenTracingServerInterceptor(opentracing.GlobalTracer())))

	// 第二步：生成一个结构体对象
	s := GreeterServer{}
	// 第三步: 把s注册到g对象中
	proto.RegisterGreeterServer(g, &s)
	// 第四步：启动服务，监听端口
	lis, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
	if err != nil {
		panic("启动服务异常")
	}

	//******** 注册grpc服务和设置健康检查********
	// 1 设置健康检查
	//health.NewServer()具体实现grpc已经帮我们写好了
	grpc_health_v1.RegisterHealthServer(g, health.NewServer())
	// 2 注册grpc服务
	grpcId := utils.GetUUId()
	RegisterConsul("127.0.0.1", port, "grpc_test", grpcId, []string{"grpc", "lqz"})
	g.Serve(lis)
}

func RegisterConsul(localIP string, localPort int, name string, id string, tags []string) error {
	config := consulapi.DefaultConfig()
	config.Address = common.ConsulAddr
	client, err := consulapi.NewClient(config)
	if err != nil {
		fmt.Println("consul client error : ", err)
	}

	// 创建注册到consul的服务到
	registration := new(consulapi.AgentServiceRegistration)
	registration.ID = id
	registration.Name = name //根据这个名称来找这个服务
	registration.Port = localPort
	//registration.Tags = []string{"lqz", "gin_web"} //这个就是一个标签，可以根据这个来找这个服务，相当于V1.1这种
	registration.Tags = tags //这个就是一个标签，可以根据这个来找这个服务，相当于V1.1这种
	registration.Address = localIP

	// 增加consul健康检查回调函数
	check := new(consulapi.AgentServiceCheck)
	check.GRPC = fmt.Sprintf("127.0.0.1:%d", localPort) // 健康检查地址只需要写grpc服务地址端口即可，会自动检查
	check.Timeout = "5s"                                //超时
	check.Interval = "5s"                               //健康检查频率
	check.DeregisterCriticalServiceAfter = "30s"        // 故障检查失败30s后 consul自动将注册服务删除
	registration.Check = check
	// 注册服务到consul
	err = client.Agent().ServiceRegister(registration)
	if err != nil {
		return err
	}
	return nil
}

func funcB() {
	fmt.Println("调用了funcB")
	time.Sleep(1 * time.Second)
}

type GreeterServer struct {
}

func (h GreeterServer) SayHello(ctx context.Context, in *proto.HelloRequest) (*proto.HelloResponse, error) {
	// **********子span使用开始**********
	// 取出父span
	parentSpan := opentracing.SpanFromContext(ctx)
	// 取出全局tracer
	tracer := opentracing.GlobalTracer()
	span2 := tracer.StartSpan("funcB", opentracing.ChildOf(parentSpan.Context()))
	funcB()
	span2.Finish()
	// **********子span使用结束**********

	// 接收客户端发送过来的数据，打印出来
	fmt.Println("客户端传入的名字是：", in.Name)
	fmt.Println("客户端传入的年龄是：", in.Age)
	return &proto.HelloResponse{
		Reply: "gin-调用grpc，grpc给的回复",
	}, nil
}
